package com.farm.common.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.OSSObject;
import com.farm.common.config.OssConfig;
import lombok.Data;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Data
@Component
public class OssUtil {

    private final OssConfig ossConfig;

    public String getObjectName(String originalFilename) {
        String extension;
        if (originalFilename != null){
            extension = StrUtil.DOT + FileUtil.extName(originalFilename);
        }else {
            return null;
        }
        // JDK8的日期格式
        LocalDateTime time = LocalDateTime.now();
        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String folder = StrUtil.format("{}/{}",ossConfig.getFolderPath(),dft.format(time));
        // 拼装OSS上存储的路径 避免文件覆盖，需要使用UUID将文件重命名
        String fileName = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        // 在OSS上bucket下的文件名
        return StrUtil.format("{}/{}{}",folder,fileName,extension);
    }

    public String upload(String objectName, MultipartFile file) {
        OSS ossClient = ossConfig.ossClient();
        try {
            ossClient.putObject(ossConfig.getBucketName(), objectName, file.getInputStream());
        } catch (IOException e) {
            ossClient.shutdown();
            throw new RuntimeException(e);
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        //文件访问路径规则
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(ossConfig.getBucketName())
                .append(".")
                .append(ossConfig.getEndpoint())
                .append("/")
                .append(objectName);

        return stringBuilder.toString();
    }

    public void download(HttpServletResponse response, String objectName,String myContentType) {
        if (ObjectUtil.isEmpty(objectName)){
            throw new RuntimeException("文件路径不能为空");
        }
        objectName = StrUtil.replace(objectName, StrUtil.format("https://{}.{}/", ossConfig.getBucketName(), ossConfig.getEndpoint()), "");
        // 创建OSSClient实例。
        OSS ossClient = ossConfig.ossClient();
        //请求的输入流 和响应的输入流
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), objectName);

            if (ObjectUtil.isNotEmpty(myContentType)){
                response.setContentType(myContentType);
                if (ObjectUtil.contains(myContentType,"download")){
                    // 下载
                    // response.setContentType("application/x-download");
                    String fileName = FileNameUtil.getName(objectName);
                    long contentLength = ossObject.getObjectMetadata().getContentLength();
                    response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                    response.addHeader("Content-Length", "" + contentLength);
                    response.setContentType("application/octet-stream");
                }
            }else{
                String contentType = ossObject.getObjectMetadata().getContentType();
                //设置响应内容类型，当设置了ContentType为“image/jpg”时，浏览器可以直接显示图片；
                response.setContentType(contentType);
            }

            outputStream = new BufferedOutputStream(response.getOutputStream());
            byte[] buf = new byte[1024];
            inputStream = ossObject.getObjectContent();
            int L;
            while ((L = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, L);
            }
        }catch (IOException e) {
            e.getMessage();
        }finally {
            IoUtil.close(inputStream);
            // 写完以后关闭文件流
            IoUtil.flush(outputStream);
            IoUtil.close(outputStream);
        }

    }


}
